﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
//using WinFormApp.tmp;

namespace WinFormApp
{

	public class MenuManager : Form
	{

		protected List<Menus> menusDB;

		public MenuManager()
		{ }

		protected void loadTreeMenu(TreeView menuTree)
		{
            menuTree.Nodes.Clear();

            // retrieve all menus from DB
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            this.menusDB = (from m in ctx.Menus select m).ToList();

            // root menus only ...
            Menus[] rootMenus = this.menusDB.FindAll(i => i.idParentMenu == null).ToArray();

            // sort them ...
            Array.Sort(rootMenus, delegate(Menus mn1, Menus mn2)
            { return (int)(mn1.MenuOrder - mn2.MenuOrder); });
			
			// add ROOT
            foreach (var item in rootMenus)
            {
                TreeNode rootNode = new TreeNode();
                rootNode.Name = item.idMenu.ToString();
                rootNode.Text = item.MenuName;
                rootNode.Tag = item;
                menuTree.Nodes.Add(rootNode);

                Menus[] subMenu = this.menusDB.FindAll(i => i.idParentMenu == item.idMenu).ToArray();

                // check if there is a subMenu for this rootMenu ...
                if (subMenu != null && subMenu.Length != 0)
                {
                    Array.Sort(subMenu, delegate(Menus mn1, Menus mn2)
                    { return (int)(mn1.MenuOrder - mn2.MenuOrder); });

                    // add SUB
                    fillNodes(subMenu,rootNode);
                }
            } 
		}

		private void fillNodes(Menus[] menus, TreeNode superNode)
		{
			foreach (var item in menus)
            {
                TreeNode node = new TreeNode();
                node.Name = item.idMenu.ToString();
                node.Text = item.MenuName;
                node.Tag = item;
                superNode.Nodes.Add(node);

                Menus[] subMenu = this.menusDB.FindAll(i => i.idParentMenu == item.idMenu).ToArray();

                if (subMenu != null && subMenu.Length != 0)
                {
                    Array.Sort(subMenu, delegate(Menus mn1, Menus mn2)
                    { return (int)(mn1.MenuOrder - mn2.MenuOrder); });

                    // ... inception :)
                    fillNodes(subMenu,node);
                }
            }
		}

		public void searchTreeView(TreeView treeMenus, TextBox txtSearch)
		{
			int numNodesNotMatch = treeMenus.Nodes.Count;
			TreeNode matchedNode = null;

			foreach (TreeNode node in treeMenus.Nodes)
			{
				int x = node.Nodes.Count;
				TreeNode xNode = null;

				foreach (TreeNode subNode in node.Nodes)
				{
					int y = subNode.Nodes.Count;
					TreeNode yNode = null;

					foreach (TreeNode subsubNode in subNode.Nodes)
					{
						if (subsubNode.Text.ToUpper().Contains(txtSearch.Text.ToUpper()) && txtSearch.Text != "")
						{
							subsubNode.ForeColor = System.Drawing.Color.Blue;
							
							y--;
							yNode = subsubNode;
						}
						else
						{
							subsubNode.ForeColor = System.Drawing.Color.Empty;
						}
					}
					if ((y + 1) == subNode.Nodes.Count)
					{
						treeMenus.SelectedNode = yNode;
						this.expandAllParentNodes(yNode);
					}
					else
					{
					}

					if (subNode.Text.ToUpper().Contains(txtSearch.Text.ToUpper()) && txtSearch.Text != "")
					{
						subNode.ForeColor = System.Drawing.Color.Blue;
						x--;
						xNode = subNode;
					}
					else
					{
						subNode.ForeColor = System.Drawing.Color.Empty;
					}
				}
				if ((x + 1) == node.Nodes.Count)
				{
					treeMenus.SelectedNode = xNode;
					this.expandAllParentNodes(xNode);
				}

				if (node.Text.ToUpper().Contains(txtSearch.Text.ToUpper()) && txtSearch.Text != "")
				{
					node.ForeColor = System.Drawing.Color.Blue;
					matchedNode = node;
					numNodesNotMatch--;
				}
				else
				{
					node.ForeColor = System.Drawing.Color.Empty;
				}
			}

			if ((numNodesNotMatch + 1) == treeMenus.Nodes.Count)
			{
				treeMenus.SelectedNode = matchedNode;
				treeMenus.SelectedNode.Expand();
			}
		}

		private void expandAllParentNodes(TreeNode node)
		{
			if (node == null) return;
			else
			{
				node.Expand();
				expandAllParentNodes(node.Parent);
			}
		}

		protected void switchNodes(object sender, DragEventArgs e, TreeView menuTree)
		{
			TreeNode dragNode, destNode;

			if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
			{
				Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));

				dragNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
				Menus dragData = (Menus)dragNode.Tag;
				int? dragNodeId = Convert.ToInt32(dragNode.Name);
				int dragIndex = this.menusDB.FindIndex(i => i.idMenu == dragNodeId);

				destNode = ((TreeView)sender).GetNodeAt(pt);
				if (destNode == null) return; // dragged to an empty space ...
				Menus destData = (Menus)destNode.Tag;
				int? destNodeId = Convert.ToInt32(destNode.Name);
				int destIndex = this.menusDB.FindIndex(i => i.idMenu == destNodeId);

				// avoid these drags ...
				if (dragData.idMenu == destData.idMenu) return;
				if (dragData.idParentMenu == destData.idMenu) return;

				DataClasses1DataContext ctx = new DataClasses1DataContext();
				Menus dragMenu = (from m in ctx.Menus where m.idMenu == dragNodeId select m).First();
				Menus destMenu = (from m in ctx.Menus where m.idMenu == destNodeId select m).First();

				// SWITCH NODE (when a node is dragged to another of the same type)
				if (dragData.MenuType.Equals(destData.MenuType))
				{
					// swap order ...
					int? tmpOrder = dragMenu.MenuOrder;
					dragMenu.MenuOrder = destMenu.MenuOrder;
					destMenu.MenuOrder = tmpOrder;

					if (dragData.idParentMenu != destData.idParentMenu)
					{
						int? tmpIdParentMenu = dragMenu.idParentMenu;
						dragMenu.idParentMenu = destMenu.idParentMenu;
						destMenu.idParentMenu = tmpIdParentMenu;
					}

					ctx.SubmitChanges();

					//selectedNode = dragNode;
					menuTree.SelectedNode = dragNode;

					loadTreeMenu(menuTree);

					// ... expand the two parent nodes
					try
					{
						menuTree.SelectedNode = menuTree.Nodes.Find(Convert.ToString(destMenu.idParentMenu), true).First();
						menuTree.SelectedNode.Expand();
						menuTree.SelectedNode = menuTree.Nodes.Find(Convert.ToString(dragMenu.idParentMenu), true).First();
						menuTree.SelectedNode.Expand();
					}
					catch (Exception) { }

					return;
				}

				TreeNode parentDragNode;
				Menus parentDragMenu;
				try
				{
					parentDragNode = menuTree.Nodes.Find(Convert.ToString(dragMenu.idParentMenu), true).First();
					parentDragMenu = parentDragNode.Tag as Menus;
				}
				catch (Exception) { return; }

				// ADD NODE (when a node is dragged to a node with the same level of the parentMenu)
				if (parentDragMenu.MenuType.Equals(destMenu.MenuType))
				{
					// get biggest menu order 
					int? biggest = menusDB.FindAll(i => i.idParentMenu == destMenu.idMenu).Max(m => m.MenuOrder);

					int? dragMenuOriginalParentID = dragMenu.idParentMenu;

					if (biggest != null)
					{
						dragMenu.MenuOrder = biggest + 1;
						dragMenu.idParentMenu = destMenu.idMenu;
					}
					else
					{
						dragMenu.MenuOrder = 1;
						dragMenu.idParentMenu = destMenu.idMenu;
					}

					ctx.SubmitChanges();

					loadTreeMenu(menuTree);

					// expand both nodes
					try
					{
						menuTree.SelectedNode = menuTree.Nodes.Find(Convert.ToString(destMenu.idMenu), true).First();
						menuTree.SelectedNode.Expand();
						menuTree.SelectedNode = menuTree.Nodes.Find(Convert.ToString(dragMenuOriginalParentID), true).First();
						menuTree.SelectedNode.Expand();
					}
					catch (Exception) { }

					return;
				}
			}
		}

		public void tmp()
		{

		}
	}
}
